<template>
  <div class="erp-form-assign">
    <div class="assign-container">
      <div class="assign-wrap">
        <div class="assign-main">
          <div class="assign-main-header">
            已分配客户列表{{ checkedList.length ? '(' + checkedList.length + ')' : '' }}
          </div>
          <div class="assign-main-body">
            <div class="assign-box">
              <div class="assign-header">
                <el-input
                  v-model="filterAssignedKeyword"
                  class="assign-search-input"
                  type="text"
                  placeholder="搜索已分配客户名称/编码"
                  prefix-icon="el-icon-search"
                  size="mini"
                  clearable
                />
                <el-button
                  v-if="checkedList.length"
                  class="assign-op-icon"
                  plain
                  @click="clearAssigned"
                >
                  全部移除
                </el-button>
              </div>
              <div class="assign-body">
                <div
                  class="customer-list"
                >
                  <template v-if="checkedList.length">
                    <div
                      v-for="item in assignedCustomerListPage(assignedCustomerPageIndex)"
                      :key="item[primaryKey]"
                      class="customer-item"
                    >
                      <div class="customer-content">
                        <div
                          class="customer-name"
                          :title="item.name"
                        >
                          {{ item.name }}
                        </div>
                        <div class="customer-info">
                          <div
                            class="customer-code"
                            :title="item.code"
                          >
                            {{ item.code }}
                          </div>
                          <div
                            class="customer-region"
                            :title="item.regionCodeShowText"
                          >
                            {{ item.regionCodeShowText }}
                          </div>
                        </div>
                      </div>
                      <div
                        class="customer-select"
                      >
                        <el-button
                          type="text"
                          size="mini"
                          class="remove-button"
                          @click="removeAssignedItem(item)"
                        >
                          移除
                        </el-button>
                      </div>
                    </div>
                  </template>
                  <template v-else>
                    <div class="empty">
                      该用户还未分配客户
                    </div>
                  </template>
                </div>
              </div>
              <div class="assign-footer">
                <el-pagination
                  layout="prev, pager, next, total"
                  :total="filterAssignedCustomerList.length"
                  :small="true"
                  :page-size="allCustomerPageSize"
                  :current-page="assignedCustomerPageIndex"
                  :hide-on-single-page="true"
                  @current-change="assignedCustomerCurrentChange"
                />
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="assign-separator">
        <i class="iconfont icon-qiehuan" />
      </div>
      <div class="assign-wrap">
        <div class="assign-main">
          <div class="assign-main-header">
            客户列表({{ checkedList.length }}/{{ allCustomerTotal }})
          </div>
          <div class="assign-main-body">
            <div class="assign-box">
              <div class="assign-header">
                <el-input
                  v-model="allCustomerKeyword"
                  class="assign-search-input"
                  type="text"
                  placeholder="搜索客户名称"
                  prefix-icon="el-icon-search"
                  size="mini"
                  clearable
                />
                <div class="assign-check-all">
                  <vxe-checkbox
                    v-model="checkedAll"
                    @change="onCheckedAll($event)"
                  />
                </div>
              </div>
              <div class="assign-body">
                <div
                  class="customer-list"
                >
                  <template v-if="allCustomerListCom.length">
                    <div
                      v-for="item in allCustomerListCom"
                      :key="item[primaryKey]"
                      class="customer-item"
                      :class="{active: item[extraCom.checkedKey]}"
                      @click.stop="checkCustomer(item)"
                    >
                      <div class="customer-content">
                        <div
                          class="customer-name"
                          :title="item.name"
                        >
                          {{ item.name }}
                        </div>
                        <div class="customer-info">
                          <div
                            class="customer-code"
                            :title="item.code"
                          >
                            {{ item.code }}
                          </div>
                          <div
                            class="customer-region"
                            :title="item.regionCodeShowText"
                          >
                            {{ item.regionCodeShowText }}
                          </div>
                        </div>
                      </div>
                      <div
                        class="customer-select"
                      >
                        <vxe-checkbox
                          v-model="item[extraCom.checkedKey]"
                          class="customer-checkbox"
                          @click.stop
                          @change="onChecked($event, item)"
                        />
                      </div>
                    </div>
                  </template>
                  <template v-else>
                    <div class="empty">
                      暂无客户信息，需要先录入客户信息
                    </div>
                  </template>
                </div>
              </div>
              <div class="assign-footer">
                <el-pagination
                  layout="prev, pager, next, total"
                  :total="allCustomerTotal"
                  :small="true"
                  :page-size="allCustomerPageSize"
                  :hide-on-single-page="true"
                  :current-page="allCustomerPageIndex"
                  @current-change="allCustomerCurrentChange"
                />
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
/**
 * @Author      : maolin
 * @Date        : 2021/6/11
 * @Version     : 1.0
 * @Description : 分配
 **/
import {base as request} from '@/request';
import {consoleWarn} from "../../../utils/console";
import XEUtils from 'xe-utils';
/**
 * 分配客户
 * @author maolin
 */
export default {
  name: "ErpFormAssignCustomer",
  components: {},
  props: {
    /**
     * 标题
     * @public
     */
    title: {
      type: String,
      default: '',
    },
    /**
     * 字段
     * @public
     */
    field: {
      type: String,
      default: ''
    },
    /**
     * 默认值
     * @public
     */
    value: {
      type: [Object, Number, Array, String],
      default () {
        return null;
      }
    },
    /**
     * 表单对象
     * @public
     */
    form: {
      type: Object,
      default () {
        return {
        };
      }
    },
    /**
     * 额外配置
     * ```js
     * return {
        primaryKey: 'id',
        userIdKey: 'userId',
        formUserIdKey: 'userId',
        checkedKey: '_checked',
        // 请求所有客户列表
        all: {
          // 请求的路由
          url: "/basCustomer/basCustomerSysUserList",
          // 关键字搜索框配置
          keyword: {
            // 关键字占位符
            placeholder: '搜索客户名称',
            // 关键字请求字段
            key: 'name',
          },
          // 分页配置
          pagination: {
            // 分页页码字段
            pageIndexKey: 'pageIndex',
            // 分页容量字段
            pageSizeKey: 'pageSize',
            // 默认页码
            defaultPageIndex: 1,
            // 默认页容量
            defaultPageSize: 50,
          }
          // 请求之后处理函数 返回的是列表
          // after({res}) {return res;},
        },
        // 已分配配置
        assigned: {
          // 请求的路由
          url: "/basCustomer/basCustomerDistributionSysUserList",
          // 关键字搜索框配置
          keyword: {
            // 关键字占位符
            placeholder: '搜索客户名称',
          },
          // 分页配置
          pagination: {
            // 分页页码字段
            pageIndexKey: 'pageIndex',
            // 分页容量字段
            pageSizeKey: 'pageSize',
            // 默认页码
            defaultPageIndex: 1,
            // 默认页容量
            defaultPageSize: 50,
          }
          // 请求之后处理函数 返回的是列表
          // after({res}) {return res;},
        }
      }
     * ```
     * @public
     */
    extra: {
      type: Object,
      default () {
        return {
        };
      }
    },
  },
  data() {
    return {
      filterAssignedKeyword: null,
      allCustomerList: [],
      checkedList: [],
      assignedCustomerList: [],
      filterAssignedCustomerList: [],
      allCustomerKeyword: null,
      allCustomerPageIndex: 1,
      allCustomerPageSize: 10,
      assignedCustomerPageIndex: 1,
      allCustomerTotal: 0,
      firstGetAssigned: true,
      checkedAll: false,
    };
  },
  computed: {

    extraCom () {
      const defaultConfig = {
        primaryKey: 'id',
        userIdKey: 'userId',
        formUserIdKey: 'userId',
        checkedKey: '_checked',
        // 请求所有客户列表
        all: {
          // 请求的路由
          url: "/basCustomer/basCustomerSysUserList",
          // 关键字搜索框配置
          keyword: {
            // 关键字占位符
            placeholder: '搜索客户名称',
            // 关键字请求字段
            key: 'name',
          },
          // 分页配置
          pagination: {
            // 分页页码字段
            pageIndexKey: 'pageIndex',
            // 分页容量字段
            pageSizeKey: 'pageSize',
            // 默认页码
            defaultPageIndex: 1,
            // 默认页容量
            defaultPageSize: 50,
          }
          // 请求之后处理函数 返回的是列表
          // after({res}) {return res;},
        },
        // 已分配配置
        assigned: {
          // 请求的路由
          url: "/basCustomer/basCustomerDistributionSysUserList",
          // 关键字搜索框配置
          keyword: {
            // 关键字占位符
            placeholder: '搜索客户名称',
          },
          // 分页配置
          pagination: {
            // 分页页码字段
            pageIndexKey: 'pageIndex',
            // 分页容量字段
            pageSizeKey: 'pageSize',
            // 默认页码
            defaultPageIndex: 1,
            // 默认页容量
            defaultPageSize: 50,
          }
          // 请求之后处理函数 返回的是列表
          // after({res}) {return res;},
        }
      };
      return Object.assign(defaultConfig, this.extra);
    },
    primaryKey () {
      return this.extraCom.primaryKey;
    },
    allCustomerListCom () {
      const {primaryKey, checkedKey} = this.extraCom;
      const checkedList = this.checkedList;
      return this.allCustomerList.map(item => {
        item[checkedKey] = checkedList.includes(item[primaryKey]);
        return item;
      });
    },
    assignedCustomerListPage () {
      return function (pageIndex) {
        let data = this.filterAssignedCustomerList;
        const pageSize = this.allCustomerPageSize;
        const start = (pageIndex - 1) * pageSize;
        const end = start + pageSize;
        return data.slice(start, end);
      };
    }
  },
  watch: {
    checkedList (v) {
      this.$emit('value-change', v.length ? v.join(',') : null);
    },
    value: {
      handler (v) {
        this.checkedList = v ? v.split(',').map(item => parseInt(item)) : [];
      },
      immediate: true
    },
    form: {
      handler(f) {
        if (JSON.stringify(f) !== '{}' && this.firstGetAssigned) {
          this.getAssignedCustomerList();
          this.firstGetAssigned = false;
        }
      },
      immediate: true,
      deep: true,
    },
    assignedCustomerList (data) {
      this.onFilter();
      this.checkedList = data.map(item => parseInt(item[this.primaryKey]));
    },
    filterAssignedKeyword() {
      this.onFilter();
    },
    allCustomerKeyword () {
      this.onSearch();
    }
  },
  created() {
    this.getAllCustomerList();
  },
  mounted() {
    this.onFilter = XEUtils.debounce(this.filterAssigned, 100, {leading: false, trailing: true});
    this.onSearch = XEUtils.debounce(this.getAllCustomerList, 500, {leading: false, trailing: true});
  },
  methods: {
    /**
     * 筛选已分配客户
     * @private
     */
    filterAssigned () {
      const keyword = this.filterAssignedKeyword;
      let data = this.assignedCustomerList;
      if (keyword) {
        this.filterAssignedCustomerList = data.filter(item => {
          return (item.name && item.name.indexOf(keyword) > -1) || (item.code && item.code.indexOf(keyword) > -1);
        });
      } else {
        this.filterAssignedCustomerList = data;
      }
      this.assignedCustomerPageIndex = 1;
    },
    /**
     * 获取所有客户列表
     * @private
     */
    getAllCustomerList () {
      const {all} = this.extraCom;
      if (!all || !all.url) {
        return ;
      }
      const {pagination, keyword, after} = all;
      let params = {};
      if (keyword && keyword.key) {
        params[keyword.key] = this.allCustomerKeyword;
      }
      if (pagination) {
        if (pagination.pageIndexKey) {
          params[pagination.pageIndexKey] = this.allCustomerPageIndex || pagination.defaultPageIndex;
        }
        if (pagination.pageSizeKey) {
          params[pagination.pageSizeKey] = this.allCustomerPageSize || pagination.defaultPageSize;
        }
      }
      request.post(all.url, params)
        .then(res => {
          let data = res.data;
          if (after && typeof after === 'function') {
            try{
              data = after({res});
            }catch (e) {
              consoleWarn(this.$options.name + ',all.after函数执行失败：' + e);
            }
          }
          this.allCustomerList = data.list;
          this.allCustomerTotal = data.total;
        })
        .catch(() => {

        });
    },
    /**
     * 获取已分配的客户列表
     * @private
     */
    getAssignedCustomerList () {
      const {assigned, userIdKey, formUserIdKey} = this.extraCom;
      if (!assigned || !assigned.url) {
        return ;
      }
      const {pagination, after} = assigned;
      let params = {};
      if (userIdKey) {
        params[userIdKey] = this.form[formUserIdKey] || '';
      }
      if (pagination) {
        if (pagination.pageIndexKey) {
          params[pagination.pageIndexKey] = this.allCustomerPageIndex || pagination.defaultPageIndex;
        }
        if (pagination.pageSizeKey) {
          params[pagination.pageSizeKey] = this.allCustomerPageSize || pagination.defaultPageSize;
        }
      }
      request.post(assigned.url, params)
        .then(res => {
          let data = res.data;
          if (after && typeof after === 'function') {
            try{
              data = after({res});
            }catch (e) {
              consoleWarn(this.$options.name + ',extra.assigned.after函数执行失败：' + e);
            }
          }
          this.assignedCustomerList = data;
          this.checkedList = data.map(item => parseInt(item[this.primaryKey]));
        })
        .catch(() => {

        });
    },
    /**
     * 选中/取消选中客户
     * @private
     */
    checkCustomer (item) {
      const primaryKey = this.primaryKey;
      let checkedList = this.checkedList;
      const index = checkedList.indexOf(item[primaryKey]);
      let assignedCustomerList = this.assignedCustomerList;
      if (index === -1){
        checkedList.unshift(item[primaryKey]);
        assignedCustomerList.unshift(item);
      } else {
        checkedList.splice(index, 1);
        assignedCustomerList.splice(index, 1);
      }
    },
    /**
     * 点击复选框
     * @private
     */
    onChecked (e, item) {
      this.checkCustomer(item);
    },
    /**
     * 全选/取消全选
     * @private
     */
    onCheckedAll (e) {
      const {checked} = e;
      // 获取所有客户中当前页的客户id
      const currentPageCustomerIds = this.allCustomerList.map(item => item[this.primaryKey]);
      this.batchEditCheckedList(currentPageCustomerIds, checked);
      this.batchEditAssignedCustomerList(this.allCustomerList,currentPageCustomerIds, checked);
    },
    /**
     * 批量修改选中的项
     * @private
     * @param {array} customerIds 选中的客户id数组
     * @param {boolean} isChecked 是否选中
     */
    batchEditCheckedList (customerIds, isChecked) {
      let checkedList = this.checkedList;
      if (isChecked) {
        // 若为选中，合并并去重
        this.checkedList = Array.from(new Set(checkedList.concat(customerIds)));
      } else {
        // 否则，移除checkedList中在customerIds中的项；
        this.checkedList = this.checkedList.filter(item => {
          return !customerIds.includes(item);
        });
      }
    },
    /**
     * 批量修改选中的项
     * @private
     * @param {array} customerList 选中的客户列表
     * @param {array} customerIds 选中的客户id列表
     * @param {boolean} isChecked 是否选中
     */
    batchEditAssignedCustomerList (customerList, customerIds, isChecked) {
      let assignedCustomerList = this.assignedCustomerList;
      const primaryKey = this.primaryKey;
      let temp = [];
      // 先移除已分配中当前选中所有的客户
      temp = assignedCustomerList.filter(item => {
        return !customerIds.includes(item[primaryKey]);
      });

      if (isChecked) {
        // 若为选中，则在头部合并当前页的数据
        this.assignedCustomerList = customerList.concat(temp);
      } else {
        this.assignedCustomerList = temp;
      }
    },
    /**
     * 所有客户切换分页页码时获取列表
     * @private
     */
    allCustomerCurrentChange (index) {
      this.allCustomerPageIndex = index;
      this.getAllCustomerList();
    },
    /**
     * 已分配客户的分页切换
     * @private
     */
    assignedCustomerCurrentChange (index) {
      this.assignedCustomerPageIndex = index;
    },
    /**
     * 移除已分配的某一项
     * @private
     */
    removeAssignedItem (item) {
      const userId = item[this.primaryKey];
      this.assignedCustomerList = this.assignedCustomerList.filter(assignedItem => {
        return assignedItem[this.primaryKey] != userId;
      });
    },
    /**
     * 移除全部已分配的客户
     * @private
     */
    clearAssigned () {
      this.checkedList.length && this.$msgbox({
        title: '提示',
        message: '确定要移除所有已分配的客户？',
        showCancelButton: true,
        type: 'warning',
        showClose: true,
        confirmButtonText: '确认',
        cancelButtonText: '取消',
      }).then(() => {
        this.checkedList = [];
        this.assignedCustomerList = [];
        this.assignedCustomerPageIndex = 1;
      }).catch(() => {});

    }
  },
};
</script>

<style lang="scss" scoped>
$primaryColor: var(--primary-color);
$primaryColor20: var(--primary-color20);
$containerHeight: 600px;
$containerWidth: 800px;
$wrapWidth: 380px;
$assignMainHeight: 33px;
$assignFooterHeight: 32px;
$borderColor: #ddd;
$selectWidth: 40px;
.erp-form-assign{
  display: block;
  width: 100%;
  box-sizing: border-box;
  .assign-container{
    margin: 0 auto;
    width: $containerWidth;
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: space-between;
    .assign-wrap{
      width: $wrapWidth;
      height: $containerHeight;
      .assign-main{
        height: 100%;
        border: 1px solid $borderColor;
        border-radius: 2px;
        .assign-main-header{
          color: #333;
          height: $assignMainHeight;
          line-height: $assignMainHeight;
          padding: 0 10px;
          font-size: 14px;
          font-weight: bold;
          border-bottom: 1px solid $borderColor;
        }
        .assign-main-body{
          height: calc(100% - #{$assignMainHeight});
          .assign-box{
            height: 100%;
            .assign-header{
              display: flex;
              flex-wrap: nowrap;
              ::v-deep{
                .el-button.assign-op-icon{
                  border-radius: 0;
                  border: 1px solid #fff;
                  border-left: 1px solid #ddd;
                  width: 80px;
                  font-size: 12px;
                  line-height: $assignMainHeight;
                  padding: 0 5px;
                  text-align: center;
                  cursor: pointer;
                  color: #333;
                  &:hover{
                    border: 1px solid $primaryColor;
                    color: $primaryColor;
                  }
                }
              }
              .assign-check-all {
                display: block;
                width: 60px;
                line-height: $assignMainHeight;
              }
              ::v-deep{
                .el-input.assign-search-input{
                  .el-input__inner{
                    border: none;
                    height: $assignMainHeight;
                    line-height: $assignMainHeight;
                  }
                }
              }
              border-bottom: 1px solid $borderColor;
            }
            .assign-body{
              height: calc(100% - #{$assignMainHeight} - #{$assignFooterHeight} - 2px);
              .customer-list{
                height: 100%;
                overflow-y: auto;
                .empty{
                  height: 50px;
                  line-height: 50px;
                  text-align: center;
                  color: #999;
                  font-size: 14px;
                }
                .customer-item{
                  cursor: pointer;
                  border-bottom: 1px solid $borderColor;
                  padding: 10px 20px;
                  display: flex;
                  flex-wrap: nowrap;
                  justify-content: space-between;
                  background-color: #fff;
                  .customer-content{
                    width: calc(100% - #{$selectWidth});
                    .customer-name{
                      overflow: hidden;
                      text-overflow: ellipsis;
                      white-space: nowrap;
                      font-size: 14px;
                      color: #333;
                    }
                    .customer-info{
                      font-size: 12px;
                      display: flex;
                      flex-wrap: nowrap;
                      justify-content: space-between;
                      overflow: hidden;
                      text-overflow: ellipsis;
                      white-space: nowrap;
                      .customer-code{
                        color: #888;
                      }
                      .customer-region{
                        margin-left: 20px;
                        color: #aaa;
                        justify-content: space-between;
                        overflow: hidden;
                        text-overflow: ellipsis;
                      }
                    }
                  }
                  .customer-select{
                    width: $selectWidth;
                    position: relative;
                    .customer-checkbox{
                      display: block;
                      width: 16px;
                      height: 16px;
                      position: absolute;
                      top: 50%;
                      right: 0;
                      transform: translateY(-50%);
                    }
                    .remove-button{
                      display: none;
                      width: 100%;
                      position: absolute;
                      top: 50%;
                      right: 0;
                      color: $primaryColor;
                      transform: translateY(-50%);
                      font-size: 12px;
                      text-align: right;
                    }

                  }
                  &:hover, &.active{
                    background-color: $primaryColor20;
                  }
                  &.active{
                    .customer-name{
                      color: $primaryColor;
                    }
                  }
                  &:hover{
                    .remove-button{
                      display: block;
                    }
                  }
                }
              }
            }
            .assign-footer{
              height: $assignFooterHeight;
              border-top: 1px solid $borderColor;
              ::v-deep{
                .el-pagination{
                  padding: 5px;
                }
              }
            }
          }
        }
      }
    }
    .assign-separator{
      height: $containerHeight;
      line-height: 100%;
      width: 40px;
      position: relative;
      i{
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
      }
    }
  }

}
</style>
